package com.os.opencv.java.chapter9;

import org.opencv.core.*;
import org.opencv.dnn.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.opencv.core.Core.minMaxLoc;
import static org.opencv.dnn.Dnn.*;

public class Laplacian {

    public static void main(String[] args) throws Exception {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        //读取图像并在屏幕上显示
        /*Mat src = Imgcodecs.imread("/Users/matt/Pictures/1700969333712.jpg", Imgcodecs.IMREAD_GRAYSCALE);
        HighGui.imshow("wanlifuwangshi", src);
        HighGui.waitKey(0);

        //高斯滤波后用Laplacian算子提取边缘
        Mat dst = new Mat();
        Imgproc.GaussianBlur(src, src, new Size(3,3), 5);
        Imgproc.Laplacian(src, dst, 0, 3);
        Core.convertScaleAbs(dst, dst);

        //计算政府图像的边缘并在屏幕上显示
        HighGui.imshow("laplacian", dst);
        HighGui.waitKey(0);


        Mat src1 = Imgcodecs.imread("/Users/matt/Pictures/1700969333712.jpg");
        HighGui.imshow("src1", src1);
        HighGui.waitKey(0);*/

        Mat dst1 = new Mat();

        /*String path = "/Users/matt/Pictures/FSRCNN_x2.pb";
        //加载模型
        Net net = readNetFromTensorflow(path);
        //图像预处理
        Mat blob = blobFromImage(src1);
        //送入神经网络
        net.setInput(blob);
        //执行推理，输出结果
        Mat output = net.forward();*/

        /**
         * https://bingbuyu.blog.csdn.net/article/details/78416887?spm=1001.2101.3001.6650.9&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-9-78416887-blog-70982048.235%5Ev39%5Epc_relevant_default_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-9-78416887-blog-70982048.235%5Ev39%5Epc_relevant_default_base&utm_relevant_index=10
         */
        /*HighGui.imshow("dst1", output);
        HighGui.waitKey(0);*/

        //https://blog.csdn.net/jiangchaobing_2017/article/details/134004283
        //以bvlc_googlenet.caffemodel为例
        String model_txt_file = "/Users/matt/Pictures/bvlc_googlenet.prototxt";//模型的描述文件
        String model_bin_file = "/Users/matt/Pictures/bvlc_googlenet.caffemodel";//模型的权重文件
        String labels_txt_file = "/Users/matt/Pictures/imagenet_labels.txt";

        Mat src = Imgcodecs.imread("/Users/matt/Pictures/smallPotDog.jpg");
        if (src.empty())
        {
            System.out.println("图片源文件为空。。。");
        }
        HighGui.imshow("src", src);
        HighGui.waitKey(0);

        //读取文本标签
        List<String> labels = readLabels(labels_txt_file);

        // 读取网络 包括模型描述文件和和模型文件
        Net net = readNetFromCaffe(model_txt_file, model_bin_file);
        if (net.empty())
        {
            System.out.println("模型文件为空。。。");
        }

        //设置计算后台
        net.setPreferableBackend(DNN_BACKEND_OPENCV);
        //设置支持设备
        net.setPreferableTarget(DNN_TARGET_CPU);

        Mat inputBlob = blobFromImage(src, 1.0, new Size(224, 224), new Scalar(104, 117, 123));
        Mat prob = new Mat();
        for (int i = 0; i < 1000; i++)
        {
            net.setInput(inputBlob, "data");
            prob = net.forward("prob");	// 输出为1×1000 1000类的概率
        }
        Mat proMat = prob.reshape(1, 1);	// 单通道 一行

        //https://vimsky.com/examples/detail/java-method-org.opencv.core.Core.minMaxLoc.html
        Core.MinMaxLocResult minMaxLocResult = minMaxLoc(proMat);
        Point classNumber = minMaxLocResult.maxLoc;
        double possibility = minMaxLocResult.maxVal;

        int classidx = (int) classNumber.x;
        System.out.println("current image classification:" + labels.get(classidx));
        System.out.println("current image possible: " + possibility);

        System.exit(0);
    }

    static List<String> readLabels(String txtFilePath) throws IOException {
        List<String> labels = new ArrayList<>();
        FileReader fr = new FileReader(txtFilePath);
        BufferedReader br = new BufferedReader(fr);
        String line;
        while ((line = br.readLine()) != null) {
            labels.add(line);
        }

        br.close();
        fr.close();
        return labels;
    }
}
